package com.lagou.minicat.core;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;

public class ContextClassLoader extends ClassLoader {

    private String classBase;

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        try {
            String classToPath = name.replace(".", "/");
            String fullPath = classBase + "/WEB-INF/classes/" + classToPath + ".class";
            File file = new File(fullPath);
            byte[] classBytes = getClassBytes(file);
            Class<?> c = this.defineClass(name, classBytes, 0, classBytes.length);
            return c;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return super.findClass(name);
    }

    private byte[] getClassBytes(File file) throws Exception {
        FileInputStream fis = new FileInputStream(file);
        FileChannel fc = fis.getChannel();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        WritableByteChannel wbc = Channels.newChannel(baos);
        ByteBuffer by = ByteBuffer.allocate(1024);

        while (true) {
            int i = fc.read(by);
            if (i == 0 || i == -1)
                break;
            by.flip();
            wbc.write(by);
            by.clear();
        }

        fis.close();

        return baos.toByteArray();
    }

    public void setClassBase(String classBase) {
        this.classBase = classBase;
    }

    @Override
    public String toString() {
        return "ContextClassLoader{" +
                "hashCode=" + Integer.toHexString(hashCode()) + ", " +
                "classBase='" + classBase + '\'' +
                '}';
    }
}
